package org.easiermock;

import org.easiermock.testmocks.AbstractDelegate;
import org.easiermock.testmocks.ExtendsDelegate;
import org.easiermock.testmocks.NotImplementerDelegate;
import org.easiermock.testmocks.RealInterface;
import org.easiermock.testmocks.RealObject;
import org.easiermock.testmocks.TestDelegate;
import org.junit.Test;

public abstract class AbstractEasierMockTest {
	
	@Test
	public void testInterfaceRealWithExtendingDelegate() {
		RealInterface mock = createConcreteMock(RealInterface.class, new ExtendsDelegate());
		testMockBehaviour(mock);
	}

	@Test
	public void testConcreteRealWithExtendingDelegate() {
		RealInterface mock = createConcreteMock(RealObject.class, new ExtendsDelegate());
		testMockBehaviour(mock);
	}

	@Test
	public void testConcreteRealWithNonExtendingDelegate() {
		RealInterface mock = createConcreteMock(RealObject.class, new NotImplementerDelegate());
		testMockBehaviour(mock);
	}
	
	@Test
	public void testInterfaceRealWithNonExtendingDelegate() {
		RealInterface mock = createConcreteMock(RealInterface.class, new NotImplementerDelegate());
		testMockBehaviour(mock);
	}
	
	@Test
	public void testInterfaceRealWithAbstractDelegate() {
		AbstractDelegate mock = createAbstractMock(AbstractDelegate.class);
		testMockBehaviour(mock);
	}
	
	protected <T extends RealInterface> void testMockBehaviour(T mock) {
		TestDelegate delegate = (TestDelegate)EasierMock.getDelegate(mock);
		testMockBehaviour(mock, delegate);
	}

	protected <T extends RealInterface> T createAbstractMock(
			Class<T> abstractDelegateClass) {
		return EasierMock.createMock(abstractDelegateClass);
	}

	protected <T extends RealInterface> T createConcreteMock(
			Class<T> realClass, TestDelegate delegate) {
		return EasierMock.createMock(realClass, delegate);
	}

	protected abstract <T extends RealInterface> void testMockBehaviour(T mock, TestDelegate delegate);
	
}
